using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using System.ComponentModel.DataAnnotations;
using System.Reflection;

namespace JGSY.CMS.LowCode.Platform.Infrastructure.Swagger;

/// <summary>
/// Swagger示例数据架构过滤器
/// </summary>
public class SwaggerExampleSchemaFilter : ISchemaFilter
{
    public void Apply(OpenApiSchema schema, SchemaFilterContext context)
    {
        if (context.Type == null) return;

        // 为枚举类型添加示例
        if (context.Type.IsEnum)
        {
            schema.Example = new OpenApiString(Enum.GetNames(context.Type)[0]);
        }

        // 为常见类型添加示例
        if (schema.Properties != null)
        {
            foreach (var property in schema.Properties)
            {
                AddExampleForProperty(property.Key, property.Value, context.Type);
            }
        }

        // 从DataAnnotations特性中提取验证信息
        AddValidationInfoFromAttributes(schema, context);
    }

    private void AddExampleForProperty(string propertyName, OpenApiSchema propertySchema, Type type)
    {
        if (propertySchema.Example != null) return;

        // 根据属性名称和类型添加示例
        switch (propertyName.ToLower())
        {
            case "id":
                propertySchema.Example = new OpenApiLong(1);
                break;
            case "name":
                propertySchema.Example = new OpenApiString("示例名称");
                break;
            case "email":
                propertySchema.Example = new OpenApiString("user@example.com");
                break;
            case "phone":
                propertySchema.Example = new OpenApiString("13800138000");
                break;
            case "url":
                propertySchema.Example = new OpenApiString("https://example.com");
                break;
            case "createdat":
            case "updatedat":
                propertySchema.Example = new OpenApiString("2025-08-08T10:30:00.000Z");
                break;
            case "isactive":
            case "enabled":
                propertySchema.Example = new OpenApiBoolean(true);
                break;
            case "status":
                propertySchema.Example = new OpenApiInteger(1);
                break;
            case "sortorder":
                propertySchema.Example = new OpenApiInteger(1);
                break;
            default:
                // 根据数据类型添加默认示例
                if (propertySchema.Type == "string" && propertySchema.Example == null)
                {
                    propertySchema.Example = new OpenApiString("示例文本");
                }
                else if (propertySchema.Type == "integer" && propertySchema.Example == null)
                {
                    propertySchema.Example = new OpenApiInteger(1);
                }
                else if (propertySchema.Type == "boolean" && propertySchema.Example == null)
                {
                    propertySchema.Example = new OpenApiBoolean(true);
                }
                break;
        }
    }

    private void AddValidationInfoFromAttributes(OpenApiSchema schema, SchemaFilterContext context)
    {
        var properties = context.Type.GetProperties();
        
        foreach (var property in properties)
        {
            var propertyName = GetJsonPropertyName(property);
            if (!schema.Properties.ContainsKey(propertyName)) continue;

            var propertySchema = schema.Properties[propertyName];

            // Required特性
            var requiredAttribute = property.GetCustomAttribute<RequiredAttribute>();
            if (requiredAttribute != null)
            {
                if (schema.Required == null) schema.Required = new HashSet<string>();
                schema.Required.Add(propertyName);
                
                if (!string.IsNullOrEmpty(requiredAttribute.ErrorMessage))
                {
                    propertySchema.Description = $"{propertySchema.Description}\n必填字段: {requiredAttribute.ErrorMessage}".Trim();
                }
            }

            // StringLength特性
            var stringLengthAttribute = property.GetCustomAttribute<StringLengthAttribute>();
            if (stringLengthAttribute != null)
            {
                propertySchema.MaxLength = stringLengthAttribute.MaximumLength;
                if (stringLengthAttribute.MinimumLength > 0)
                    propertySchema.MinLength = stringLengthAttribute.MinimumLength;
                
                if (!string.IsNullOrEmpty(stringLengthAttribute.ErrorMessage))
                {
                    propertySchema.Description = $"{propertySchema.Description}\n长度限制: {stringLengthAttribute.ErrorMessage}".Trim();
                }
            }

            // Range特性
            var rangeAttribute = property.GetCustomAttribute<RangeAttribute>();
            if (rangeAttribute != null)
            {
                if (rangeAttribute.Minimum is int min)
                    propertySchema.Minimum = min;
                if (rangeAttribute.Maximum is int max)
                    propertySchema.Maximum = max;
                
                if (!string.IsNullOrEmpty(rangeAttribute.ErrorMessage))
                {
                    propertySchema.Description = $"{propertySchema.Description}\n取值范围: {rangeAttribute.ErrorMessage}".Trim();
                }
            }

            // RegularExpression特性
            var regexAttribute = property.GetCustomAttribute<RegularExpressionAttribute>();
            if (regexAttribute != null)
            {
                propertySchema.Pattern = regexAttribute.Pattern;
                
                if (!string.IsNullOrEmpty(regexAttribute.ErrorMessage))
                {
                    propertySchema.Description = $"{propertySchema.Description}\n格式要求: {regexAttribute.ErrorMessage}".Trim();
                }
            }
        }
    }

    private string GetJsonPropertyName(PropertyInfo property)
    {
        // 检查JsonPropertyName特性
        var jsonPropertyNameAttribute = property.GetCustomAttribute<System.Text.Json.Serialization.JsonPropertyNameAttribute>();
        if (jsonPropertyNameAttribute != null)
        {
            return jsonPropertyNameAttribute.Name;
        }

        // 默认使用驼峰命名
        var name = property.Name;
        return char.ToLowerInvariant(name[0]) + name.Substring(1);
    }
}
